package ocp.context.xml;

import com.sun.org.apache.xerces.internal.parsers.SAXParser;
import ocp.context.*;
import org.xml.sax.helpers.*;
import org.xml.sax.*;

/**
 * This class is the root of all XML context readers. Every context reader
 * reads an XML file and returns some contextual information that can be
 * interpreted by a context to form a concrete contextual information.
 * @author Ignacio Nieto Carvajal.
 */
public abstract class XMLContextReader extends DefaultHandler 
{
    protected static final String DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser";

	protected boolean running = false;
	protected String xmlFile = null;	
	protected SAXParser parser = null;
	protected String parserName = DEFAULT_PARSER_NAME;
	protected int level = 0;

	/** 
	 * The main constructor of the class. Takes the xml uri to be read and the
	 * context that wants to read the xml file as arguments.
	 */
	public XMLContextReader(String xmlFile)
	{
		this.xmlFile = xmlFile;
		running = false;
		// creates a Xerces XML parser.
		try
		{
			parser = new SAXParser();
                        parser.setFeature("http://xml.org/sax/features/validation", true);
			parser.setContentHandler(this);
		} catch (SAXNotRecognizedException e) {
            System.err.println (e);
            } catch (SAXNotSupportedException e) {
                System.err.println (e);
            }
	}

	/** An alternate constructor of the class. Sets the parser name
	 * @param parserName the name of the parser to use.
	 */
	public XMLContextReader(String xmlFile, String parserName)
	{
		this(xmlFile);
		this.parserName = parserName;
	}
	
	public void startDocument()
	{
		running = true;
		level = 0;
	}
	
	public void endDocument()  
	{
		// we are ready to parse again.
		running = false;
	}

	public abstract void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException;

	public abstract void endElement(String uri, String localName, String qName) throws SAXException;

    //  Warning Event Handler
    public void warning (SAXParseException e)
        throws SAXException {
        System.err.println ("Warning:  "+e);
    }

    //  Error Event Handler
    public void error (SAXParseException e)
        throws SAXException {
        System.err.println ("Error:  "+e);
		System.exit(-2);
    }
    
    //  Fatal Error Event Handler
    public void fatalError (SAXParseException e)
        throws SAXException {
        System.err.println ("Fatal Error:  "+e);
		System.exit(-3);
    }
   
	/** returns true if the parser is running, false otherwise. */
	public boolean isRunning()	{ return running; }

	/** this method must be override by subclasses of XMLContextReader. It
	 * returns an especific context information object to be returned when
	 * called from the "read" method.
	 */
	public abstract Object readContext() throws 
		IncompatibleContextualObjectException;
	
	public Object read() throws IncompatibleContextualObjectException
	{
		if (!running)
		{
	        try 
		{
                        running = true;
			parser = new SAXParser();
                        parser.setContentHandler(this);
                        parser.setErrorHandler(this);
                        parser.parse(xmlFile);
			return readContext();
	        } catch (Exception e) { e.printStackTrace(System.err); }
                    finally	{ running = false; }
		}
		else
		{
			System.err.println("XML parser running. Try again later.");
		}
		return null;
	}
}

